package net.tv90.volunteerserveradmin.service;

import jakarta.annotation.Resource;
import jakarta.persistence.criteria.Predicate;
import net.tv90.volunteerserveradmin.dao.*;
import net.tv90.volunteerserveradmin.exception.ServiceException;
import net.tv90.volunteerserveradmin.model.domain.Image;
import net.tv90.volunteerserveradmin.model.domain.Student;
import net.tv90.volunteerserveradmin.model.domain.Teacher;
import net.tv90.volunteerserveradmin.model.domain.VolunteerProject;
import net.tv90.volunteerserveradmin.model.dto.QueryDTO;
import net.tv90.volunteerserveradmin.model.dto.VolunteerProjectDTO;
import net.tv90.volunteerserveradmin.model.dto.VolunteerProjectQueryDTO;
import net.tv90.volunteerserveradmin.utils.entity.Assert;
import net.tv90.volunteerserveradmin.utils.entity.PageResult;
import net.tv90.volunteerserveradmin.model.vo.StudentVO;
import net.tv90.volunteerserveradmin.model.vo.TeacherVO;
import net.tv90.volunteerserveradmin.model.vo.VolunteerProjectVO;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;
import java.util.stream.Collectors;

@Service
public class VolunteerProjectService {

    @Resource
    private VolunteerProjectRepository volunteerProjectRepository;
    @Resource
    private VolunteerProjectRelationRepository volunteerProjectRelationRepository;
    @Resource
    private ProjectTeacherRelationRepository projectTeacherRelationRepository;
    @Resource
    private StudentRepository studentRepository;
    @Resource
    private TeacherRepository teacherRepository;
    @Resource
    private ImageService imageService;

    public VolunteerProjectVO getVolunteerProjectById(Long id) throws ServiceException {
        // 查询志愿活动基本信息
        VolunteerProject volunteerProject = volunteerProjectRepository.findById(id)
                .orElseThrow(() -> new ServiceException("Volunteer Project not found"));

        // 获取学生列表
        List<Long> studentIds = volunteerProjectRelationRepository.findVolunteerIdsByProjectId(id);
        List<StudentVO> studentVOs = studentIds.stream()
                .map(studentId -> {
                    Student student = studentRepository.findById(studentId)
                            .orElse(Student.newStudent());
                    return convertToStudentVO(student);
                })
                .collect(Collectors.toList());

        // 获取教师列表
        List<Long> teacherIds = projectTeacherRelationRepository.findTeacherIdsByProjectId(id);
        List<TeacherVO> teacherVOs = teacherIds.stream()
                .map(teacherId -> {
                    Teacher teacher = teacherRepository.findById(teacherId)
                            .orElse(Teacher.newTeacher());
                    return convertToTeacherVO(teacher);
                })
                .collect(Collectors.toList());

        Image img = imageService.getImageById(volunteerProject.getImageId());

        VolunteerProjectVO vo = convertToVO(volunteerProject);
        vo.setStudents(studentVOs);
        vo.setTeachers(teacherVOs);
        vo.setImage(img);
        return vo;
    }

    public List<VolunteerProjectVO> getAllVolunteerProjects() throws ServiceException {
        List<VolunteerProject> projects = volunteerProjectRepository.findAll();
        return projects.stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
    }

    @Transactional(rollbackFor = Exception.class)
    public void addVolunteerProject(VolunteerProjectDTO volunteerProjectDTO, MultipartFile file) throws ServiceException {
        Assert.assertNotNull("需要上传图片信息！", HttpStatus.BAD_REQUEST, file);
        VolunteerProject volunteerProject = new VolunteerProject();
        BeanUtils.copyProperties(volunteerProjectDTO, volunteerProject);
        Image img = imageService.uploadImage(file);
        volunteerProject.setImageId(img.getId());
        volunteerProjectRepository.save(volunteerProject);
    }

    @Transactional(rollbackFor = Exception.class)
    public void updateVolunteerProject(Long id, VolunteerProjectDTO volunteerProjectDTO, MultipartFile file) throws ServiceException {
        VolunteerProject volunteerProject = volunteerProjectRepository.findById(id)
                .orElseThrow(() -> new ServiceException("Volunteer Project not found"));
        BeanUtils.copyProperties(volunteerProjectDTO, volunteerProject);
        if(file != null) {
            Image img = imageService.uploadImage(file);
            volunteerProject.setImageId(img.getId());
        }
        volunteerProjectRepository.save(volunteerProject);
    }

    @Transactional(rollbackFor = Exception.class)
    public void deleteVolunteerProject(Long id) throws ServiceException {
        VolunteerProject volunteerProject = volunteerProjectRepository.findById(id)
                .orElseThrow(() -> new ServiceException("Volunteer Project not found"));
        volunteerProjectRepository.delete(volunteerProject);
    }

    private VolunteerProjectVO convertToVO(VolunteerProject volunteerProject) {
        VolunteerProjectVO vo = new VolunteerProjectVO();
        BeanUtils.copyProperties(volunteerProject, vo);
        return vo;
    }

    private StudentVO convertToStudentVO(Student student) {
        StudentVO vo = new StudentVO();
        vo.setStudentId(student.getId());
        vo.setName(student.getName());
        vo.setStudentNumber(student.getStudentNumber());
        vo.setGender(student.getGender());
        return vo;
    }

    private TeacherVO convertToTeacherVO(Teacher teacher) {
        TeacherVO vo = new TeacherVO();
        vo.setTeacherId(teacher.getId());
        vo.setName(teacher.getName());
        vo.setStaffNumber(teacher.getStaffNumber());
        vo.setGender(teacher.getGender());
        return vo;
    }

    public PageResult<VolunteerProjectVO> queryVolunteerProject(VolunteerProjectQueryDTO dto) {
        if (dto.getPage() == null || dto.getPage() < 1) {
            dto.setPage(1);
        }
        if (dto.getPageNum() == null || dto.getPageNum() < 10 || dto.getPageNum() > 100) {
            dto.setPageNum(10);
        }
        if (dto.getOrderBy() == null || dto.getOrderBy().isEmpty()) {
            dto.setOrderBy("id");
        }
        if (dto.getDesc() == null) {
            dto.setDesc(0);
        }

        Sort sort = dto.getDesc() == 1 ? Sort.by(dto.getOrderBy()).descending() : Sort.by(dto.getOrderBy()).ascending();
        PageRequest pageRequest = PageRequest.of(dto.getPage() - 1, dto.getPageNum(), sort);

        Specification<VolunteerProject> spec = (root, query, criteriaBuilder) -> {
            Predicate predicate = criteriaBuilder.conjunction();

            if (dto.getTitle() != null && !dto.getTitle().isEmpty()) {
                predicate = criteriaBuilder.and(predicate,
                        criteriaBuilder.like(root.get("title"), "%" + dto.getTitle() + "%"));
            }

            if (dto.getLocation() != null && !dto.getLocation().isEmpty()) {
                predicate = criteriaBuilder.and(predicate,
                        criteriaBuilder.like(root.get("location"), "%" + dto.getLocation() + "%"));
            }

            // 性别限制过滤，0表示不限，忽略该过滤条件
            if (dto.getGenderLimit() != null && dto.getGenderLimit() != 0) {
                predicate = criteriaBuilder.and(predicate,
                        criteriaBuilder.equal(root.get("genderLimit"), dto.getGenderLimit()));
            }

            // 根据 status 字段的逻辑处理
            if (dto.getStatus() != null) {
                if (dto.getStatus() == -1) {
                    // -1 表示查询所有状态，无需添加过滤条件
                } else if (dto.getStatus() == -2) {
                    // -2 表示查询未结束的活动 (status: 0, 1, 2)
                    predicate = criteriaBuilder.and(predicate,
                            criteriaBuilder.or(
                                    criteriaBuilder.equal(root.get("status"), 0),
                                    criteriaBuilder.equal(root.get("status"), 1),
                                    criteriaBuilder.equal(root.get("status"), 2)
                            ));
                } else {
                    // 其他具体状态 (0, 1, 2, 3)
                    predicate = criteriaBuilder.and(predicate,
                            criteriaBuilder.equal(root.get("status"), dto.getStatus()));
                }
            }

            return predicate;
        };

        Page<VolunteerProject> projectPage = volunteerProjectRepository.findAll(spec, pageRequest);

        // 修改这里：将图片加入到 VO 中
        List<VolunteerProjectVO> list = projectPage.getContent().stream()
                .map(project -> {
                    VolunteerProjectVO vo = convertToVO(project);
                    if (project.getImageId() != null) {
                        Image image = imageService.getImageById(project.getImageId());
                        vo.setImage(image);
                    }
                    return vo;
                })
                .collect(Collectors.toList());

        return new PageResult<>(list, projectPage.getTotalElements());
    }


    public PageResult<VolunteerProjectVO> getVolunteerProjectsByStudentId(Long studentId, QueryDTO dto) {
        if (dto.getPage() == null || dto.getPage() < 1) {
            dto.setPage(1);
        }
        if (dto.getPageNum() == null || dto.getPageNum() < 10 || dto.getPageNum() > 100) {
            dto.setPageNum(10);
        }
        if (dto.getOrderBy() == null || dto.getOrderBy().isEmpty()) {
            dto.setOrderBy("id");
        }
        if (dto.getDesc() == null) {
            dto.setDesc(0);
        }
        // 验证学生是否存在
        studentRepository.findById(studentId)
                .orElseThrow(() -> new ServiceException("学生信息不存在！"));

        // 查询该学生参与的项目ID
        List<Long> projectIds = volunteerProjectRelationRepository.findProjectIdsByVolunteerId(studentId);
        if (projectIds.isEmpty()) {
            return new PageResult<>(List.of(), 0L); // 返回空分页结果
        }

        // 构造分页请求
        PageRequest pageRequest = PageRequest.of(
                dto.getPage() == null ? 0 : dto.getPage() - 1,
                dto.getPageNum() == null ? 10 : dto.getPageNum(),
                Sort.by(Sort.Direction.fromString(dto.getDesc() == 1 ? "DESC" : "ASC"), dto.getOrderBy() == null ? "id" : dto.getOrderBy())
        );

        // 查询分页结果
        Page<VolunteerProject> projectPage = volunteerProjectRepository.findByIdIn(projectIds, pageRequest);

        // 转换为 VO
        List<VolunteerProjectVO> list = projectPage.getContent().stream()
                .map(project -> {
                    VolunteerProjectVO vo = convertToVO(project);
                    if (project.getImageId() != null) {
                        Image image = imageService.getImageById(project.getImageId());
                        vo.setImage(image);
                    }
                    return vo;
                })
                .collect(Collectors.toList());

        return new PageResult<>(list, projectPage.getTotalElements());
    }


    public PageResult<VolunteerProjectVO> getVolunteerProjectsByTeacherId(Long teacherId, QueryDTO dto) {
        if (dto.getPage() == null || dto.getPage() < 1) {
            dto.setPage(1);
        }
        if (dto.getPageNum() == null || dto.getPageNum() < 10 || dto.getPageNum() > 100) {
            dto.setPageNum(10);
        }
        if (dto.getOrderBy() == null || dto.getOrderBy().isEmpty()) {
            dto.setOrderBy("id");
        }
        if (dto.getDesc() == null) {
            dto.setDesc(0);
        }
        // 验证教师是否存在
        teacherRepository.findById(teacherId)
                .orElseThrow(() -> new ServiceException("教师信息不存在！"));
        // 查询该教师参与的项目ID
        List<Long> projectIds = projectTeacherRelationRepository.findProjectIdsByTeacherId(teacherId);
        if (projectIds.isEmpty()) {
            return new PageResult<>(List.of(), 0L); // 返回空分页结果
        }
        // 构造分页请求
        PageRequest pageRequest = PageRequest.of(
                dto.getPage() == null ? 0 : dto.getPage() - 1,
                dto.getPageNum() == null ? 10 : dto.getPageNum(),
                Sort.by(Sort.Direction.fromString(dto.getDesc() == 1 ? "DESC" : "ASC"), dto.getOrderBy() == null ? "id" : dto.getOrderBy())
        );
        // 查询分页结果
        Page<VolunteerProject> projectPage = volunteerProjectRepository.findByIdIn(projectIds, pageRequest);
        // 转换为 VO
        List<VolunteerProjectVO> list = projectPage.getContent().stream()
                .map(project -> {
                    VolunteerProjectVO vo = convertToVO(project);
                    if (project.getImageId() != null) {
                        Image image = imageService.getImageById(project.getImageId());
                        vo.setImage(image);
                    }
                    return vo;
                })
                .collect(Collectors.toList());
        return new PageResult<>(list, projectPage.getTotalElements());
    }

}
